package broker

import (
    "strings"
    "sync"
    
    "github.com/yangyongzhen/mqtt-broker/internal/protocol/common"
)

type TopicManager struct {
    subscriptions map[string]map[string]*common.Subscription // topic -> clientID -> subscription
    mu            sync.RWMutex
}

func NewTopicManager() *TopicManager {
    return &TopicManager{
        subscriptions: make(map[string]map[string]*common.Subscription),
    }
}

func (tm *TopicManager) Subscribe(clientID string, subscription *common.Subscription) {
    tm.mu.Lock()
    defer tm.mu.Unlock()
    
    if tm.subscriptions[subscription.Topic] == nil {
        tm.subscriptions[subscription.Topic] = make(map[string]*common.Subscription)
    }
    tm.subscriptions[subscription.Topic][clientID] = subscription
}

func (tm *TopicManager) Unsubscribe(clientID string, topic string) {
    tm.mu.Lock()
    defer tm.mu.Unlock()
    
    if clients, exists := tm.subscriptions[topic]; exists {
        delete(clients, clientID)
        if len(clients) == 0 {
            delete(tm.subscriptions, topic)
        }
    }
}

func (tm *TopicManager) RemoveClientSubscriptions(clientID string) {
    tm.mu.Lock()
    defer tm.mu.Unlock()
    
    for topic, clients := range tm.subscriptions {
        delete(clients, clientID)
        if len(clients) == 0 {
            delete(tm.subscriptions, topic)
        }
    }
}

func (tm *TopicManager) GetSubscribers(topic string) map[string]*common.Subscription {
    tm.mu.RLock()
    defer tm.mu.RUnlock()
    
    subscribers := make(map[string]*common.Subscription)
    
    for subTopic, clients := range tm.subscriptions {
        if tm.topicMatch(topic, subTopic) {
            for clientID, subscription := range clients {
                // 如果同一个客户端有多个匹配的订阅，选择QoS最高的
                if existing, exists := subscribers[clientID]; !exists || subscription.QoS > existing.QoS {
                    subscribers[clientID] = subscription
                }
            }
        }
    }
    
    return subscribers
}

func (tm *TopicManager) GetTopicCount() int {
    tm.mu.RLock()
    defer tm.mu.RUnlock()
    return len(tm.subscriptions)
}

func (tm *TopicManager) GetSubscriptionCount() int {
    tm.mu.RLock()
    defer tm.mu.RUnlock()
    
    count := 0
    for _, clients := range tm.subscriptions {
        count += len(clients)
    }
    return count
}

func (tm *TopicManager) topicMatch(topic, filter string) bool {
    // 实现MQTT主题匹配规则
    // 支持通配符 + 和 #
    
    if filter == topic {
        return true
    }
    
    filterParts := strings.Split(filter, "/")
    topicParts := strings.Split(topic, "/")
    
    return tm.matchParts(topicParts, filterParts, 0, 0)
}

func (tm *TopicManager) matchParts(topic, filter []string, ti, fi int) bool {
    // 如果过滤器已经处理完
    if fi >= len(filter) {
        return ti >= len(topic)
    }
    
    // 如果遇到多级通配符 #
    if filter[fi] == "#" {
        return true
    }
    
    // 如果主题已经处理完但过滤器还有
    if ti >= len(topic) {
        return false
    }
    
    // 如果是单级通配符 + 或者完全匹配
    if filter[fi] == "+" || filter[fi] == topic[ti] {
        return tm.matchParts(topic, filter, ti+1, fi+1)
    }
    
    return false
}

// 验证主题名称是否有效
func (tm *TopicManager) IsValidTopicName(topic string) bool {
    if len(topic) == 0 {
        return false
    }
    
    // 主题名称不能包含通配符
    if strings.Contains(topic, "+") || strings.Contains(topic, "#") {
        return false
    }
    
    return true
}

// 验证主题过滤器是否有效
func (tm *TopicManager) IsValidTopicFilter(filter string) bool {
    if len(filter) == 0 {
        return false
    }
    
    parts := strings.Split(filter, "/")
    
    for i, part := range parts {
        if part == "#" {
            // # 必须是最后一个部分
            if i != len(parts)-1 {
                return false
            }
        } else if part == "+" {
            // + 可以在任何位置，但必须是完整的级别
            continue
        } else if strings.Contains(part, "+") || strings.Contains(part, "#") {
            // 通配符不能与其他字符混合
            return false
        }
    }
    
    return true
}
